package com.xiao.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiao.domain.ResponseResult;
import com.xiao.domain.dto.AddSysUserDto;
import com.xiao.domain.dto.SaveUpdateSysUserDto;
import com.xiao.domain.dto.UserListDto;
import com.xiao.domain.pojo.SysUserRole;
import com.xiao.domain.vo.*;
import com.xiao.enums.AppHttpCodeEnum;
import com.xiao.exception.SystemException;
import com.xiao.mapper.BlogSysUserMapper;
import com.xiao.domain.pojo.BlogSysUser;
import com.xiao.mapper.SysUserRoleMapper;
import com.xiao.service.BlogSysUserService;
import com.xiao.service.SysRoleService;
import com.xiao.service.SysUserRoleService;
import com.xiao.utils.BeanCopyUtils;
import com.xiao.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class BlogSysUserServiceImpl extends ServiceImpl<BlogSysUserMapper, BlogSysUser> implements BlogSysUserService {

    @Autowired
    // 因为 这里是 blog-framework 公共模块 并没有装配 这个 bean 不过我们在 使用其他模块调用它是没有问题的
    private PasswordEncoder passwordEncoder;

    @Override
    public ResponseResult updateUserInfo(UserInfoVo userInfoVo) {
        // 使用 VO 为了防止 有人 使用 PostMan 恶意多上传 password ,导致不可预料的bug
        BlogSysUser user = BeanCopyUtils.copyBean(userInfoVo, BlogSysUser.class);
        this.updateById(user); // 修改用户信息,为空的字段 不会处理，不会 set 成 空
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult userInfo() {
        // 1. 通过 Security 上下文获取当前用户ID
        Long userId = SecurityUtils.getUserId();

        // 2. 根据ID 查询用户
        BlogSysUser user = this.getById(userId);

        // 3. 包装成 Vo
        UserInfoVo userInfoVo = BeanCopyUtils.copyBean(user, UserInfoVo.class);

        // 4. 统一响应格式
        ResponseResult result = ResponseResult.okResult(userInfoVo);

        return result;
    }

    @Override
    public ResponseResult register(BlogSysUser blogSysUser) {
        // 为空效验
        if (!StringUtils.hasText(blogSysUser.getUserName())){
            throw new SystemException(AppHttpCodeEnum.USERNAME_NOT_NULL);
        }
        if (!StringUtils.hasText(blogSysUser.getPassword())){
            throw new SystemException(AppHttpCodeEnum.PASSWORD_NOT_NULL);
        }
        if (!StringUtils.hasText(blogSysUser.getEmail())){
            throw new SystemException(AppHttpCodeEnum.EMAIL_NOT_NULL);
        }
        if (!StringUtils.hasText(blogSysUser.getNickName())){
            throw new SystemException(AppHttpCodeEnum.NICKNAME_NOT_NULL);
        }
        // 是否存在效验  后期考虑换成 到 Redis中查询
        if (this.userNameExists(blogSysUser.getUserName())){
            throw new SystemException(AppHttpCodeEnum.USERNAME_EXIST);
        }
        if (this.nikeNameExists(blogSysUser.getNickName())){
            throw new SystemException(AppHttpCodeEnum.NICKNAME_EXIST);
        }
        if (this.emailExists(blogSysUser.getEmail())){
            throw new SystemException(AppHttpCodeEnum.EMAIL_EXIST);
        }
        String encodePassword = passwordEncoder.encode(blogSysUser.getPassword());
        blogSysUser.setPassword(encodePassword);

        super.save(blogSysUser);// 相当于 insert

        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult<PageVo> userList(Integer pageNum, Integer pageSize, UserListDto userListDto) {

        // 1、创建构造条件
        BlogSysUser blogSysUser = BeanCopyUtils.copyBean(userListDto, BlogSysUser.class);

        LambdaQueryWrapper<BlogSysUser> wrapper = new LambdaQueryWrapper<>();

        wrapper.like(StringUtils.hasText(blogSysUser.getUserName()),BlogSysUser::getUserName,blogSysUser.getUserName());
        wrapper.like(StringUtils.hasText(blogSysUser.getPhoneNumber()),BlogSysUser::getPhoneNumber,blogSysUser.getPhoneNumber());
        wrapper.eq(StringUtils.hasText(blogSysUser.getStatus()),BlogSysUser::getStatus,blogSysUser.getStatus());


        wrapper.orderByAsc(BlogSysUser::getId);

        // 2、创建分页
        Page<BlogSysUser> userPage = new Page<>();
        userPage.setCurrent(pageNum);
        userPage.setSize(pageSize);

        // 3、查询
        Page<BlogSysUser> page = this.page(userPage, wrapper);

        List<BlogSysUser> records = page.getRecords();
        // 4、 查询结果转化 VO
        List<UserListVo> userListVos = BeanCopyUtils.copyBeanList(records, UserListVo.class);

        // 5、封装成 PageVo

        PageVo pageVo = new PageVo(userListVos, page.getTotal());

        // 6、返回统一响应
        ResponseResult result = ResponseResult.okResult(pageVo);

        return result;
    }

    @Autowired
    SysUserRoleService sysUserRoleService;
    @Override
    @Transactional // 涉及到 两个表的插入 需要事务支持
    public ResponseResult addSysUser(AddSysUserDto addSysUserDto) {
        ResponseResult result;
        // 1. 新增用户
        BlogSysUser blogSysUser = BeanCopyUtils.copyBean(addSysUserDto, BlogSysUser.class);

       if (StringUtils.hasText(blogSysUser.getUserName())){ // 如果 != null
           if (this.userNameExists(blogSysUser.getUserName())){
               result = ResponseResult.errorResult(AppHttpCodeEnum.USERNAME_EXIST);// 用户名已经存在
               return result;
           }
       }else { // 没有
           result = ResponseResult.errorResult(AppHttpCodeEnum.REQUIRE_USERNAME); // 用户名不能为空
           return result;
       }

        if (StringUtils.hasText(blogSysUser.getNickName())){ // 如果 != null
            if (this.nikeNameExists(blogSysUser.getNickName())){
                result = ResponseResult.errorResult(AppHttpCodeEnum.NICKNAME_EXIST);// 昵称 已经存在
                return result;
            }
        }else { // 没有
            result = ResponseResult.errorResult(AppHttpCodeEnum.NICKNAME_NOT_NULL); // 昵称 不能为空
            return result;
        }

        if (StringUtils.hasText(blogSysUser.getPhoneNumber())){ // 如果 != null
            if (this.phoneNumberExists(blogSysUser.getPhoneNumber())){
                result = ResponseResult.errorResult(AppHttpCodeEnum.PHONENUMBER_EXIST);// 手机号码已经存在
                return result;
            }
        }

        if (StringUtils.hasText(blogSysUser.getEmail())){ // 如果 != null
            if (this.emailExists(blogSysUser.getEmail())){
                result = ResponseResult.errorResult(AppHttpCodeEnum.EMAIL_EXIST);// 邮箱已经存在
                return result;
            }
        }

        // 加密
        blogSysUser.setPassword( passwordEncoder.encode(blogSysUser.getPassword()));

        boolean save01 = this.save(blogSysUser);

        // 2. 角色与用户关联表插入数据
        List<String> roleIds = addSysUserDto.getRoleIds();

        List<SysUserRole> collect = roleIds.stream()
                .map(r -> new SysUserRole(blogSysUser.getId(), Long.valueOf(r)))
                .collect(Collectors.toList());

        boolean save02 = sysUserRoleService.saveBatch(collect);


        result =ResponseResult.okResult();



        return result;
    }

    @Override
    public Boolean delSysUserById(List<Long> ids) {
        int i = this.getBaseMapper().deleteBatchIds(ids);
        Boolean isDel ;
        if (i==ids.size()){
            isDel=true;
        }else {
            isDel=false;
        }
        return isDel;
    }

    @Autowired
    SysUserRoleMapper sysUserRoleMapper; // 注入 mapper

    @Autowired
    SysRoleService sysRoleService;

    @Override
    public ResponseResult updateSysUserById(Long id) {
        ResponseResult responseResult;

        if (!StringUtils.hasText(String.valueOf(id))){ // 如果 id 为空;
            responseResult = ResponseResult.errorResult(AppHttpCodeEnum.CONTENT_IS_NULL); // 提示信息: "操作数据为空"
            return responseResult;
        }

        // 1. 读取用户信息
        BlogSysUser blogSysUser = this.getById(id);
        UpdateSysUserInfoVo userInfoVo = BeanCopyUtils.copyBean(blogSysUser, UpdateSysUserInfoVo.class);

        // 2. 读取当前角色拥有的角色列表;
        List<String> roleList = sysUserRoleMapper.getRoleListByUserId(id);
        // 3. 读取所有角色列表
        List<AllRoleListVo> allRoleList = sysRoleService.getAllRoleList();
        // 4. 封装
        UpdateSysUserVo updateSysUserVo = new UpdateSysUserVo(roleList,allRoleList,userInfoVo);
        // 5. 统一响应
        responseResult = ResponseResult.okResult(updateSysUserVo);

        return responseResult;
    }

    @Override
    public ResponseResult saveUpdate(SaveUpdateSysUserDto saveUpdateSysUserDto) {
        ResponseResult responseResult;

        if (!StringUtils.hasText(String.valueOf(saveUpdateSysUserDto.getId()))){ // 如果 id 为空;
            responseResult = ResponseResult.errorResult(AppHttpCodeEnum.CONTENT_IS_NULL); // 提示信息: "操作数据为空"
            return responseResult;
        }

        // 1. 更新用户数据
        BlogSysUser blogSysUser = BeanCopyUtils.copyBean(saveUpdateSysUserDto, BlogSysUser.class);
        boolean update = this.updateById(blogSysUser);
        // 2. 更新 用户与角色关系
        // 删除已有数据
        LambdaQueryWrapper<SysUserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUserRole::getUserId,blogSysUser.getId());
        sysUserRoleService.getBaseMapper().delete(wrapper);
        // 插入最新关联关系
        List<String> roleIds = saveUpdateSysUserDto.getRoleIds();
        boolean insert=true;
        if (roleIds.size()!=0){
            List<SysUserRole> collect = roleIds.stream()
                    .map(r -> new SysUserRole(blogSysUser.getId(), Long.valueOf(r)))
                    .collect(Collectors.toList());

             insert = sysUserRoleService.saveBatch(collect);
        }


        // 3. 统一响应
        if (update&&insert){
            responseResult=ResponseResult.okResult();
        }else {
            responseResult=ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR);
        }
        return responseResult;
    }


    private boolean userNameExists(String userName){
        LambdaQueryWrapper<BlogSysUser> wrapper = new LambdaQueryWrapper<>(); // 泛型必须定义为 pojo 映射对象
        wrapper.eq(BlogSysUser::getUserName,userName);
        boolean isExists = this.count(wrapper) > 0; // count() >0 则存在
        return  isExists;
    }
    private boolean nikeNameExists(String nikeName){
        LambdaQueryWrapper<BlogSysUser> wrapper = new LambdaQueryWrapper<>(); // 泛型必须定义为 pojo 映射对象
        wrapper.eq(BlogSysUser::getNickName,nikeName);
        boolean isExists = this.count(wrapper) > 0; // count() >0 则存在
        return  isExists;
    }
    private boolean emailExists(String email){
        LambdaQueryWrapper<BlogSysUser> wrapper = new LambdaQueryWrapper<>(); // 泛型必须定义为 pojo 映射对象
        wrapper.eq(BlogSysUser::getEmail,email);
        boolean isExists = this.count(wrapper) > 0; // count() >0 则存在
        return  isExists;
    }

    private boolean phoneNumberExists(String phoneNumber){
        LambdaQueryWrapper<BlogSysUser> wrapper = new LambdaQueryWrapper<>(); // 泛型必须定义为 pojo 映射对象
        wrapper.eq(BlogSysUser::getPhoneNumber,phoneNumber);
        boolean isExists = this.count(wrapper) > 0; // count() >0 则存在
        return  isExists;
    }
}
